package com.xjscrm.console.chat.handler;

import com.alibaba.fastjson.JSON;
import com.xjscrm.console.chat.cache.CacheHolder;
import com.xjscrm.console.chat.core.ChatMsgHandler;
import com.xjscrm.console.chat.frame.recv.RBaseMsg;
import com.xjscrm.console.chat.frame.send.SResultMsg;
import com.xjscrm.console.chat.utils.ChannelUtils;
import com.xjscrm.console.chat.utils.JsonUtils;
import com.xjscrm.console.chat.utils.RMsgHandlerHolder;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Slf4j
@Component
@ChannelHandler.Sharable
public class WebSocketServerHandler extends ChannelInboundHandlerAdapter {

    @Autowired
    private CacheHolder cacheHolder;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        log.info("有链接上线了: {}", ctx.channel().remoteAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("有链接下线了: {}", ctx.channel().remoteAddress());
        Long staff = ChannelUtils.getStaff(ctx.channel());
        if (Objects.nonNull(staff)) {
            cacheHolder.delStaffChannel(staff);
            cacheHolder.delStaffTag(staff);
            cacheHolder.delStaffChannelId(staff);
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 处理WebSocket消息
        if (msg instanceof TextWebSocketFrame) {

            TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) msg;

            String text1 = textWebSocketFrame.text();
            RBaseMsg frameWrapperMsg = JSON.parseObject(text1, RBaseMsg.class);
            ChatMsgHandler chatMsgHandler = RMsgHandlerHolder.matchProcessor(frameWrapperMsg.getMsgType());
            if (Objects.isNull(chatMsgHandler)) {
                ctx.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(SResultMsg.fail(frameWrapperMsg, "消息类型不支持"))));
                return;
            }
            chatMsgHandler.handle(ctx, text1);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error(cause.getMessage(), cause);
        ctx.writeAndFlush(new TextWebSocketFrame(JsonUtils.toJson(SResultMsg.fail(null, "系统繁忙,请稍后重试!"))));
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            log.info("检测到读写事件超时....");
            IdleStateEvent stateEvent = (IdleStateEvent) evt;
            switch (stateEvent.state()) {
                case READER_IDLE:
                    ChannelUtils.setCloseAttr(ctx.channel(), "60秒内没有读事件, 服务端主动终止连接");
                    break;
                case WRITER_IDLE:
                    ChannelUtils.setCloseAttr(ctx.channel(), "60秒内没有写事件, 服务端主动终止连接");
                    break;
                case ALL_IDLE:
                    ChannelUtils.setCloseAttr(ctx.channel(), "60秒内没有读写事件, 服务端主动终止连接");
                    break;
            }
            ctx.writeAndFlush(new TextWebSocketFrame("{\"close\": \"true\"}")).addListener(future -> ctx.close());
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}
